(function() {
  function Service($, Backbone, _, Event) {
    var serviceCollection = {};

    return function(url) {
      if (serviceCollection[url])
        return serviceCollection[url];
      var service = _.clone(Backbone.Events);
      service.query = function(reqData) {
        $.ajax({
          url: url,
          data: reqData,
          dataType: 'json',
          success: function(rspData) {
            service.trigger('querySuccess', rspData);
          },
          error: function(xhr, type) {
            Event.trigger('netError');
          }
        });
      }
      serviceCollection[url] = service;
      return service;
    }
  }

  var root = this;

  // AMD registration happens at the end for compatibility with AMD loaders
  // that may not enforce next-turn semantics on modules. Even though general
  // practice for AMD registration is to be anonymous, underscore registers
  // as a named module because, like jQuery, it is a base library that is
  // popular enough to be bundled in a third party lib, but not be part of
  // an AMD load request. Those cases could generate an error when an
  // anonymous define() is called outside of a loader request.
  if (typeof define === 'function' && define.amd) {
    //define unnamed module will be better
    define([
      'jquery',
      'backbone',
      'underscore',
      'event'
    ], function($, Backbone, _, Event) {
      return Service($, Backbone, _, Event);
    });
  } else {
    root["Service"] = Service($, Backbone, _, Event);
  }

}());